{
 "cells": [
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "# 做一个线性回归",
   "id": "34b8005d93722f8d"
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "## 1.构建一个线性回归的X和y",
   "id": "9c8b368f5c5b7a99"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-21T06:04:23.256793Z",
     "start_time": "2025-02-21T06:04:18.897102Z"
    }
   },
   "cell_type": "code",
   "source": [
    "import numpy as np\n",
    "import torch \n",
    "import torch.nn as nn"
   ],
   "id": "c1f830d39784a4a6",
   "outputs": [],
   "execution_count": 1
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-21T06:05:18.408984Z",
     "start_time": "2025-02-21T06:05:18.399011Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# x = 0,1,2,3,4,5,6,7,8,9,10\n",
    "x_values = [i for i in range(11)]\n",
    "x_train = np.array(x_values, dtype=np.float32)\n",
    "x_train = x_train.reshape(-1,1)\n",
    "x_train.shape"
   ],
   "id": "c2f22ac51da92fb",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(11, 1)"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 2
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-21T06:06:02.507408Z",
     "start_time": "2025-02-21T06:06:02.497432Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# y = 2 * x + 1\n",
    "y_values = [2 * x + 1 for x in x_train] \n",
    "y_train = np.array(y_values, dtype=np.float32)\n",
    "y_train = y_train.reshape(-1,1)\n",
    "y_train.shape"
   ],
   "id": "aad6fbdfc14cd5b4",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(11, 1)"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 3
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "## 2.实现线性回归\n",
    "其实线性回归就是一个不加激活函数的全连接层"
   ],
   "id": "b83de70626939103"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-21T06:09:06.867593Z",
     "start_time": "2025-02-21T06:09:06.861257Z"
    }
   },
   "cell_type": "code",
   "source": [
    "class LinearRegressionModel(nn.Module):\n",
    "    def __init__(self, input_dim, output_dim):\n",
    "        super(LinearRegressionModel, self).__init__()\n",
    "        self.linear = nn.Linear(input_dim, output_dim)\n",
    "    def forward(self, x):\n",
    "        x = self.linear(x)\n",
    "        return x"
   ],
   "id": "f7a2a9059d80569d",
   "outputs": [],
   "execution_count": 4
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-21T06:09:27.241165Z",
     "start_time": "2025-02-21T06:09:27.232219Z"
    }
   },
   "cell_type": "code",
   "source": [
    "input_dim = 1\n",
    "output_dim = 1\n",
    "model = LinearRegressionModel(input_dim, output_dim)\n"
   ],
   "id": "cf845ff689f63e9",
   "outputs": [],
   "execution_count": 5
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "## 3.指定好参数和损失函数",
   "id": "796f1477c036ff7d"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-21T06:21:22.490141Z",
     "start_time": "2025-02-21T06:21:20.835024Z"
    }
   },
   "cell_type": "code",
   "source": [
    "epochs = 1000 # 训练轮次\n",
    "learning_rate = 0.01 # 学习率\n",
    "optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate) # 优化器\n",
    "criterion = nn.MSELoss() # 损失函数，均方误差"
   ],
   "id": "76d7af18a01e8827",
   "outputs": [],
   "execution_count": 6
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "## 4.训练模型",
   "id": "c59df1b87332c838"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-21T06:26:06.474380Z",
     "start_time": "2025-02-21T06:26:05.771636Z"
    }
   },
   "cell_type": "code",
   "source": [
    "for epoch in range(epochs):\n",
    "    epoch += 1\n",
    "    # 注意转换为tensor\n",
    "    inputs = torch.from_numpy(x_train)\n",
    "    labels = torch.from_numpy(y_train)\n",
    "    # 每次迭代都需要梯度清零\n",
    "    optimizer.zero_grad()\n",
    "    # 前向传播\n",
    "    outputs = model(inputs)\n",
    "    # 计算损失\n",
    "    loss = criterion(outputs, labels)\n",
    "    # 反向传播\n",
    "    loss.backward()\n",
    "    # 更新权重参数\n",
    "    optimizer.step()\n",
    "    if epoch % 50 == 0: # 每隔50次打印\n",
    "        print(\"epoch: {}, loss: {}\".format(epoch, loss.item()))\n",
    "    "
   ],
   "id": "d55e4f65045f64a7",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "epoch: 50, loss: 0.005705897696316242\n",
      "epoch: 100, loss: 0.0032544091809540987\n",
      "epoch: 150, loss: 0.0018562156474217772\n",
      "epoch: 200, loss: 0.0010587021242827177\n",
      "epoch: 250, loss: 0.0006038299179635942\n",
      "epoch: 300, loss: 0.0003444049507379532\n",
      "epoch: 350, loss: 0.00019643940322566777\n",
      "epoch: 400, loss: 0.00011204432667000219\n",
      "epoch: 450, loss: 6.390542694134638e-05\n",
      "epoch: 500, loss: 3.6453548091230914e-05\n",
      "epoch: 550, loss: 2.0790554117411375e-05\n",
      "epoch: 600, loss: 1.1859668120450806e-05\n",
      "epoch: 650, loss: 6.763693363609491e-06\n",
      "epoch: 700, loss: 3.858363470499171e-06\n",
      "epoch: 750, loss: 2.2002750483807176e-06\n",
      "epoch: 800, loss: 1.2540571106001153e-06\n",
      "epoch: 850, loss: 7.155563821470423e-07\n",
      "epoch: 900, loss: 4.0824070879352803e-07\n",
      "epoch: 950, loss: 2.3271272198144288e-07\n",
      "epoch: 1000, loss: 1.3286530986533762e-07\n"
     ]
    }
   ],
   "execution_count": 7
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "## 5.测试模型预测结果",
   "id": "622f67cacdb57621"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-21T06:30:48.048462Z",
     "start_time": "2025-02-21T06:30:48.039757Z"
    }
   },
   "cell_type": "code",
   "source": [
    "predicted = model(torch.from_numpy(x_train).requires_grad_()).data.numpy()\n",
    "predicted"
   ],
   "id": "5c3134592ecb204d",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 1.000678 ],\n",
       "       [ 3.0005803],\n",
       "       [ 5.0004826],\n",
       "       [ 7.0003853],\n",
       "       [ 9.000287 ],\n",
       "       [11.00019  ],\n",
       "       [13.0000925],\n",
       "       [14.999994 ],\n",
       "       [16.999897 ],\n",
       "       [18.999798 ],\n",
       "       [20.9997   ]], dtype=float32)"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 8
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "## 6.模型的保存和读取",
   "id": "ea5c92c762034b19"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-21T06:31:43.168429Z",
     "start_time": "2025-02-21T06:31:43.155020Z"
    }
   },
   "cell_type": "code",
   "source": [
    "torch.save(model.state_dict(), 'model.pkl')\n",
    "model.load_state_dict(torch.load('model.pkl'))"
   ],
   "id": "ff7290a97516e83b",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<All keys matched successfully>"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 9
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "## 7.使用GPU训练\n",
    "只需要把数据和模型放入cuda即可"
   ],
   "id": "a671dfec28f84cc"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-21T06:39:23.004243Z",
     "start_time": "2025-02-21T06:39:20.417961Z"
    }
   },
   "cell_type": "code",
   "source": [
    "import numpy as np\n",
    "import torch \n",
    "import torch.nn as nn\n",
    "class LinearRegressionModel(nn.Module):\n",
    "    def __init__(self, input_dim, output_dim):\n",
    "        super(LinearRegressionModel, self).__init__()\n",
    "        self.linear = nn.Linear(input_dim, output_dim)\n",
    "    def forward(self, x):\n",
    "        x = self.linear(x)\n",
    "        return x\n",
    "    \n",
    "input_dim = 1\n",
    "output_dim = 1\n",
    "model = LinearRegressionModel(input_dim, output_dim)    \n",
    "\n",
    "device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')\n",
    "model.to(device)\n",
    "\n",
    "epochs = 1000 # 训练轮次\n",
    "learning_rate = 0.01 # 学习率\n",
    "optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate) # 优化器\n",
    "criterion = nn.MSELoss() # 损失函数，均方误差\n",
    "\n",
    "for epoch in range(epochs):\n",
    "    epoch += 1\n",
    "    # 注意转换为tensor\n",
    "    inputs = torch.from_numpy(x_train).to(device)\n",
    "    labels = torch.from_numpy(y_train).to(device)\n",
    "    # 每次迭代都需要梯度清零\n",
    "    optimizer.zero_grad()\n",
    "    # 前向传播\n",
    "    outputs = model(inputs)\n",
    "    # 计算损失\n",
    "    loss = criterion(outputs, labels)\n",
    "    # 反向传播\n",
    "    loss.backward()\n",
    "    # 更新权重参数\n",
    "    optimizer.step()\n",
    "    if epoch % 50 == 0: # 每隔50次打印\n",
    "        print(\"epoch: {}, loss: {}\".format(epoch, loss.item()))"
   ],
   "id": "6272fc00c9b1e13d",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "epoch: 50, loss: 0.2471132129430771\n",
      "epoch: 100, loss: 0.14094410836696625\n",
      "epoch: 150, loss: 0.08038917928934097\n",
      "epoch: 200, loss: 0.045851025730371475\n",
      "epoch: 250, loss: 0.026151716709136963\n",
      "epoch: 300, loss: 0.01491597294807434\n",
      "epoch: 350, loss: 0.00850752741098404\n",
      "epoch: 400, loss: 0.004852376878261566\n",
      "epoch: 450, loss: 0.0027676154859364033\n",
      "epoch: 500, loss: 0.0015785414725542068\n",
      "epoch: 550, loss: 0.0009003399754874408\n",
      "epoch: 600, loss: 0.000513513688929379\n",
      "epoch: 650, loss: 0.00029289329540915787\n",
      "epoch: 700, loss: 0.00016705207235645503\n",
      "epoch: 750, loss: 9.528072405373678e-05\n",
      "epoch: 800, loss: 5.434430931927636e-05\n",
      "epoch: 850, loss: 3.099636160186492e-05\n",
      "epoch: 900, loss: 1.7679523807601072e-05\n",
      "epoch: 950, loss: 1.0083656889037229e-05\n",
      "epoch: 1000, loss: 5.751949629484443e-06\n"
     ]
    }
   ],
   "execution_count": 10
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "## 8.HUB的使用\n",
    "模型地址： https://pytorch.org/hub/\n",
    "github地址： https://github.com/pytorch/hub"
   ],
   "id": "69647dbd9c0a6b40"
  },
  {
   "metadata": {},
   "cell_type": "code",
   "outputs": [],
   "execution_count": null,
   "source": "",
   "id": "6dfad1b789373065"
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
